package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filters.BitmapFilter;
	import flash.filters.BlurFilter;
	import flash.filters.ColorMatrixFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.text.TextLineMetrics;
	import flash.utils.getTimer;

	[SWF(width=465, height=465, backgroundColor=0x000000, frameRate=60)]
	public class ParticleClock extends Sprite
	{

		private var _bitmap:Bitmap;

		private var _bitmapData:BitmapData;

		private var _colorTransform:ColorTransform;

		private var _filter:BitmapFilter = new BlurFilter(4, 4, 1);

		private var _filter2:BitmapFilter = new ColorMatrixFilter([1, 0, 0, 0, 0,
			0, 1, 0, 0, 0,
			0, 0, 1, 0, 0,
			0, 0, 0, 0.98, 0,]);

		private var _lastTime:int;

		private var _point:Point = new Point;

		private var _pointsX:Object;

		private var _pointsY:Object;

		private var _setupTime:uint;

		private var _sizes:Object;

		private var _tail:Particle;

		public function ParticleClock()
		{
			_pointsX = {};
			_pointsY = {};
			_sizes = {};

			for each (var ch:String in "0123456789:".split(""))
			{
				var tf:TextField = new TextField();
				tf.defaultTextFormat = new TextFormat("Arial", 100, 0);
				tf.text = ch;

				var line:TextLineMetrics = tf.getLineMetrics(0);
				var w:int = Math.ceil(line.width);
				var h:int = Math.ceil(line.height);
				var bitmap:BitmapData = new BitmapData(w, h, true, 0);
				bitmap.draw(tf);

				var index:int = 0;
				var v:Vector.<uint> = bitmap.getVector(bitmap.rect);
				var pointsX:Vector.<uint> = new Vector.<uint>();
				var pointsY:Vector.<uint> = new Vector.<uint>();
				_pointsX[ch] = pointsX;
				_pointsY[ch] = pointsY;
				_sizes[ch] = bitmap.rect;

				for (var i:int = 0, len:int = v.length; i < len; i++)
				{
					if (v[i] === 0xff000000)
					{
						pointsX[index] = i % w;
						pointsY[index] = int(i / w);
						++index;
					}
				}
			}

			for (var j:int = 0; j < 10000; j++)
			{
				_tail = new Particle(_tail);
			}

			_colorTransform = new ColorTransform(0.5, 0.8, 0.8, 0.9);

			_bitmapData = new BitmapData(465, 465, true, 0);
			_bitmap = new Bitmap(_bitmapData);
			addChild(_bitmap);

			addEventListener(Event.ENTER_FRAME, enterFrameHandler);
		}

		private function enterFrameHandler(e:Event):void
		{
			var time:uint = getTimer();

			if (int(time / 2000) !== _lastTime)
			{
				_lastTime = int(time / 2000);
				setupParticle();
			}

			var diff:int = getTimer() - _setupTime;
			var particle:Particle = _tail;
			_bitmapData.lock();
			_bitmapData.applyFilter(_bitmapData, _bitmapData.rect, _point, _filter);

			while (particle !== null)
			{
				if (particle.stopped)
				{
					particle = particle.prev;
					continue;
				}

				var t:Number = particle.duration == 0 ? 1 : diff / particle.duration;
				if (t >= 1.0)
				{
					t = 1.0;
					particle.stopped;
				}
				t *= t;

				particle.x = particle.sx * (1 - t) * (1 - t) + particle.cx * t * (1 - t) + particle.ex * t * t;
				particle.y = particle.sy * (1 - t) * (1 - t) + particle.cy * t * (1 - t) + particle.ey * t * t;

				_bitmapData.setPixel32(particle.x, particle.y, int(((1 - t) * 0.3 + 0.7) * 255) * 0x1000000 + particle.color);
				particle = particle.prev;
			}

			_bitmapData.applyFilter(_bitmapData, _bitmapData.rect, _point, _filter2);
			_bitmapData.unlock();
		}


		private function setupParticle():void
		{
			var date:String = new Date().toTimeString().substring(0, 8);
			var w:int = 0;
			var h:int = 0;
			var offsets:Array = [];

			for (var i:int = 0; i < 8; i++)
			{
				offsets[i] = w;
				var rect:Rectangle = _sizes[date.charAt(i)];
				w += rect.width;
				h = h < rect.height ? rect.height : h;
			}

			var particle:Particle = _tail;
			var offsetX:int = Math.random() * (465 - w);
			var offsetY:int = Math.random() * (465 - h);
			while (particle !== null)
			{
				var chIndex:int = Math.random() * 8;
				var ch:String = date.charAt(chIndex);
				var pointsX:Vector.<uint> = _pointsX[ch];
				var pointsY:Vector.<uint> = _pointsY[ch];
				var index:int = Math.random() * pointsX.length;

				particle.sx = particle.ex;
				particle.sy = particle.ey;
				particle.ex = pointsX[index] + offsets[chIndex] + offsetX + Math.pow(Math.random(), 2) * 10 - 5;
				particle.ey = pointsY[index] + offsetY + +Math.pow(Math.random(), 2) * 10 - 5;
				particle.cx = Math.random() * 465 * 4 - 465;
				particle.cy = Math.random() * 465 * 4 - 465;

				var dx:Number = particle.sx - particle.ex;
				var dy:Number = particle.sy - particle.ey;
				particle.duration = Math.random() * 1000 + 1000;
				particle.stopped = false;

				particle = particle.prev;
			}

			_setupTime = getTimer();
		}
	}
}

class Particle
{

	public var color:uint;

	public var cx:Number;

	public var cy:Number;

	public var duration:int;

	public var ex:Number;

	public var ey:Number;

	public var prev:Particle;

	public var stopped:Boolean;

	public var sx:Number;

	public var sy:Number;

	public var x:Number;

	public var y:Number;

	public function Particle(prev:Particle)
	{
		this.prev = prev;
		duration = 0;
		stopped = true;

		sx = 0;
		sy = 0;
		ex = 0;
		ey = 0;
		cx = 0;
		cy = 0;

		color = 0;
		while (color === 0)
		{
			color += Math.random() > 0.5 ? 0xff0000 : 0;
			color += Math.random() > 0.5 ? 0x00ff00 : 0;
			color += Math.random() > 0.5 ? 0x0000ff : 0;
		}
	}
}
